<template>
  <h2>reactive的使用</h2>
  <h3>名字：{{ user.name }}</h3>
  <h3>年龄：{{ user.age }}</h3>
  <h3>性别：{{ user.gender }}</h3>
  <h3>媳妇：{{ user.wife }}</h3>
  <hr/>
  <button @click="updateUser">更新数据</button>
</template>

<script lang="ts">
import { defineComponent, reactive } from "vue";

export default defineComponent({
  name: "App",
  // 需求：显示用户的相关信息，点击按钮，可以更新用户的相关信息数据

  /*
    作用: 定义多个数据的响应式
    const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
    响应式转换是“深层的”：会影响对象内部所有嵌套的属性
    内部基于 ES6 的 Proxy 实现，通过代理对象操作源对象内部数据都是响应式的
   */
  setup() {
    // 把复杂数据变成响应式的数据
    // 返回的是一个Proxy的代理对象，被代理的目标对象就是obj对象
    // user现在是代理对象，obj是布标对象
    const obj: any = { // 为了使obj.gender不出现报错才这样写
    // const obj = {
      name: "小明",
      age: 20,
      wife: {
        name: "小甜甜",
        age: 18,
        cars: ["奔驰", "宝马", "奥迪"],
      },
    }
    // user对象的类型是Proxy
    const user = reactive<any>(obj);
    console.log(user)

    // 方法
    const updateUser = () => {
      // 直接使用目标对象的方式来更新目标对象中的成员的值，是不可能的，只能使用代理对象的方式来更新数据
      // obj.name += '===
      // user.name += "==";
      // user.age += 2;
      // user.wife.name += "++";
      // user.wife.cars.push("玛莎拉蒂");

      // user ---> 代理对象，user---->目标对象
      // user对象或者obj对象添加一个属性，哪一种方式可以引起页面变化
      // obj.gender = '男' //这种方式界面没有更新渲染
      user.gender = '男' // 这种方式，界面发生变化

      // user对象或者obj对象移除一个属性，哪一种方式可以引起页面变化
      // delete obj.age // 界面没有渲染
      delete user.age // 界面渲染了

      // 总结：如果操作代理对象，目标对象中的数据也会随之变化，同时如果想要在操作数据的时候，界面也要跟着重写更新渲染，那么也是操作代理对象
      // 通过当前的代理对象找到该对象中的某个属性，更改属性中的某个数组的数据

      user.wife.cars[1] = '玛莎拉蒂'

      // 通过当前的代理对象把目标对象中的某个数组属性添加一个新的属性
      user.wife.cars[3] = '奥拓'
    };
    return {
      user,
      updateUser,
    };
  },
});
</script>